/*
 * Class Player
 *
 * Version 1.0
 *
 * Thursday, August 14, 2008
 *
 * Created by Palidino76
 */

package palidino76.rs2.players;

import java.net.Socket;
import palidino76.rs2.Engine;
import palidino76.rs2.io.Frames;
import palidino76.rs2.net.PlayerSocket;
import palidino76.rs2.util.Stream;
import palidino76.rs2.util.Misc;
import palidino76.rs2.npcs.NPC;
import palidino76.rs2.players.items.PlayerWeapon;
import palidino76.rs2.players.combat.PlayerCombat;

public class Player {
    /**
     * Player's index.
     */
    public int playerId = 0;
    /**
     * Class for storing and converting bytes.
     */
    public Stream stream = new Stream(500, 5000);
    /**
     * Player's socket for handling most io operations.
     */
    public PlayerSocket socket;
    /**
     * Set to true if the player has finished the login stage.
     */
    public boolean online = false;
    /**
     * Player's username.
     */
    public String username = "null";
    /**
     * Player's password.
     */
    public String password = "";
    /**
     * Player's rights.
     */
    public int rights = 2;
    /**
     * 1 set to true means socket disconnected but logged in, both for removing the player.
     */
    public boolean[] disconnected = new boolean[2];
    /**
     * Gives quick access to the frame class.
     */
    public Frames frames = Engine.frames;
    /**
     * The region this player is in.
     */
    public int mapRegionX = 0;
    public int mapRegionY = 0;
    /**
     * The position this player is at in the map region.
     */
    public int currentX = 0;
    public int currentY = 0;
    /**
     * Absolute coordinates this player is at.
     */
    public int absX = 0;
    public int absY = 0;
    /**
     * The height level this player is at.
     */
    public int heightLevel = 0;
    /**
     * If either are above -1 then the player is in motion.
     */
    public int walkDir = -1;
    public int runDir = -1;
    /**
     * True if the player is running, false if it isn't.
     */
    public boolean isRunning = false;
    /**
     * Set to true if the player has entered a new map region.
     */
    public boolean mapRegionDidChange = false;
    /**
     * Set to true if teleported.
     */
    public boolean didTeleport = false;
    /**
     * Set Absolute coordinates to these.
     */
    public int teleportToX = -1;
    public int teleportToY = -1;
    /**
     * True if the player is Reqing an update.
     */
    public boolean updateReq = false;
    /**
     * Max number of steps this player can have pending.
     */
    public int walkingQueueSize = 50;
    public int wQueueReadPtr = 0;
    public int wQueueWritePtr = 0;
    /**
     * Positions the player is Reqing to walk to.
     */
    public int[] walkingQueueX = new int[walkingQueueSize];
    public int[] walkingQueueY = new int[walkingQueueSize];
    public int[] walkingQueue = new int[walkingQueueSize];
    /**
     * All the players within distance.
     */
    public Player[] playerList = new Player[Engine.players.length];
    /**
     * All the players stored in distance.
     */
    public byte[] playersInList = new byte[Engine.players.length];
    public int playerListSize = 0;
    /**
     * True if chatting is Reqing to be sent.
     */
    public boolean chatTextUpdateReq = false;
    public String chatText = "";
    public int chatTextEffects = 0;
    /**
     * True if an appearance update is needed.
     */
    public boolean appearanceUpdateReq = false;
    /**
     * Animation data.
     */
    public boolean animUpdateReq = false;
    public int animReq = -1;
    public int animDelay = 0;
    /**
     * GFX data.
     */
    public boolean gfxUpdateReq = false;
    public int gfxReq = -1;
    public int gfxDelay = 0;
    /**
     * Player and NPC facing data.
     */
    public boolean faceToUpdateReq = false;
    public int faceToReq = -1;
    /**
     * Damage data.
     */
    public boolean hit1UpdateReq = false;
    public boolean hit2UpdateReq = false;
    public int hitDiff1 = 0;
    public int hitDiff2 = 0;
    public int posionHit1 = 0;
    public int posionHit2 = 0;
    /**
     * Skill level data.
     */
    public int[] skillLvl = new int[25];
    public int[] skillXP = new int[25];
    public int combatLevel = 0;
    /**
     * Player headicons.
     */
    public int pkIcon = -1;
    public int prayerIcon = -1;
    /**
     * Equipment data.
     */
    public int[] equipment = new int[14];
    public int[] equipmentN = new int[14];
    public int[] equipmentBonus = new int[12];
    /**
     * Player appearance.
     */
    public int[] color = new int[5];
    public int[] look = new int[7];
    public int npcType = -1;
    public int gender = 0;
    /**
     * Player emotes.
     */
    public int runEmote = 0x338;
    public int walkEmote = 0x333;
    public int standEmote = 0x328;
    public int attackEmote = 422;
    /**
     * All the NPCs within distance.
     */
    public NPC[] npcList = new NPC[Engine.npcs.length];
    /**
     * All the npcs stored in distance.
     */
    public byte[] npcsInList = new byte[Engine.npcs.length];
    public int npcListSize = 0;
    /**
     * Rebuild the entire NPC list.
     */
    public boolean rebuildNPCList = false;
    /**
     * An array storing all the players items.
     */
    public int[] items = new int[28];
    public int[] itemsN = new int[28];
    /**
     * Open interfaces, use these to confirm an interface is open when trying to use one.
     */
    public int interfaceId = -1;
    public int chatboxInterfaceId = -1;
    /**
     * The current position in the login stage.
     */
    public int loginStage = 0;
    /**
     * Click x position.
     */
    public int clickX = 0;
    /**
     * Click y position.
     */
    public int clickY = 0;
    /**
     * Click id.
     */
    public int clickId = 0;
    /**
     * True if the player is trying to pickup an item.
     */
    public boolean itemPickup = false;
    /**
     * True if the player is dead.
     */
    public boolean isDead = false;
    /**
     * Set run energy.
     */
    public boolean runEnergyUpdateReq = false;
    /**
     * Wilderness ditch jump data.
     */
    public int jumpDelay = 0;
    public boolean jumpUpdateReq = true;
    /**
     * Amount of current run energy.
     */
    public int runEnergy = 100;
    /**
     * Delay before run energy can increase.
     */
    public int runEnergyDelay = 0;
    /**
     * Clicked the first option on a player.
     */
    public boolean playerOption1 = false;
    /**
     * Clicked the second option on a player.
     */
    public boolean playerOption2 = false;
    /**
     * Clicked the third option on a player.
     */
    public boolean playerOption3 = false;
    /**
     * Clicked the first option on a NPC.
     */
    public boolean npcOption1 = false;
    /**
     * Clicked the first option on an object.
     */
    public boolean objectOption1 = false;
    /**
     * Setting the players weapon.
     */
    public PlayerWeapon playerWeapon = new PlayerWeapon(this);
    /**
     * Clicked the second option on an object.
     */
    public boolean objectOption2 = false;
    /**
     * Clicked the second option on a NPC.
     */
    public boolean npcOption2 = false;
    /**
     * Forced chat.
     */
    public String forceChat = "";
    public boolean forceChatUpdateReq = false;
    /**
     * Stat restore delay.
     */
    public int statRestoreDelay = 75;
    /**
     * Teleporting variables.
     */
    public int teleX = -1;
    public int teleY = -1;
    public int teleDelay = -1;
    public int teleFinishGFX = 0;
    public int teleFinishGFXHeight = 0;
    public int teleFinishAnim = 0;
    /**
     * Attacking interface data.
     */
    public int attackStyle = 0;
    public int autoRetaliate = 0;
    /**
     * Special bar data.
     */
    public boolean specialAmountUpdateReq = false;
    public int specialAmountDelay = 0;
    public int specialAmount = 100;
    public boolean usingSpecial = false;
    /**
     * Skull data.
     */
    public int skulledDelay = 0;
    public boolean skulledUpdateReq = false;
    /**
     * Eat data.
     */
    public int eatDelay = 0;
    /**
     * Delay before recieving packets.
     */
    public boolean showAttackOption = false;
    public int clickDelay = -1;
    public int attackDelay = 5;
    public long loginTimeout = System.currentTimeMillis();
    public int deathDelay = 7;
    public boolean afterDeathUpdateReq = false;
    public int deathMessage = 0;
    public int attackPlayer = 0;
    public boolean attackingPlayer = false;
    public int combatDelay = 0;
    public int messageCount = 0;
    public int memberCount = 0;
    public int[] bankItems = new int[500];
    public int[] bankItemsN = new int[500];

    /**
     * Constructs a new Player.
     * @param socket The socket this Player belongs to.
     * @param id The index this player is at.
     */
    public Player(Socket socket, int id) {
        this.socket = new PlayerSocket(this, socket);
        playerId = id;
        look[1] = 10;
        look[2] = 18;
        look[3] = 26;
        look[4] = 33;
        look[5] = 36;
        look[6] = 42;
        for (int i = 0; i < skillLvl.length; i++) {
            skillLvl[i] = 99;
            skillXP[i] = 200000000;
        }
        for (int i = 0; i < items.length; i++) {
            items[i] = -1;
        }
        for (int i = 0; i < equipment.length; i++) {
            equipment[i] = -1;
        }
        for (int i = 0; i < bankItems.length; i++) {
            bankItems[i] = -1;
        }
    }

    /**
     * This method is called every 600 milliseconds.
     * <p>While this is good for for changing integers, this
     * should not be abused. Things that can be handled else where should
     * be done in that way, such as clicking the accept button in trade
     * should update in the ActionsButton class rather than Reqing
     * an update for the process to handle.
     */
    public void process() {
        if (disconnected[0]) {
            disconnected[1] = true;
        }
        if (statRestoreDelay > 0) {
            statRestoreDelay--;
        }
        if (clickDelay > 0) {
            clickDelay--;
        }
        if (combatDelay > 0) {
            combatDelay--;
        }
        if (teleDelay > 0) {
            teleDelay--;
        }
        if(isDead) {
		deathDelay--;
		applyDead();
	  }
        if (eatDelay > 0) {
            eatDelay--;
        }
        if(skulledDelay > 0) {
		skulledDelay--;
		skulledUpdateReq = true;
	  }
        if(jumpDelay > 0) {
		jumpDelay--;
		jumpUpdateReq = true;
	  }
        if (runEnergyDelay > 0) {
            runEnergyDelay--;
        } else {
            if (runEnergy < 100) {
                runEnergy++;
                runEnergyUpdateReq = true;
            }
            runEnergyDelay = 4;
        }
	  if (runEnergy == 0) {
		    frames.setConfig(this, 173, 0);
		    isRunning = false;
	  }
        if (specialAmountDelay > 0) {
            specialAmountDelay--;
        } else {
            if (specialAmount < 100) {
                specialAmount++;
                specialAmountUpdateReq = true;
            }
            specialAmountDelay = 2;
        }
        if (itemPickup) {
            Engine.packets.pickupItem.handlePacket(this, 0, 0);
        }
        if (playerOption1) {
            Engine.packets.playerOption1.handlePacket(this, 0, 0);
        }
        if (playerOption2) {
            Engine.packets.playerOption2.handlePacket(this, 0, 0);
        }
        if (playerOption3) {
            Engine.packets.playerOption3.handlePacket(this, 0, 0);
        }
        if (npcOption1) {
            Engine.packets.npcOption1.handlePacket(this, 0, 0);
        }
        if (npcOption2) {
            Engine.packets.npcOption2.handlePacket(this, 0, 0);
        }
        if (objectOption1) {
            Engine.packets.objectOption1.handlePacket(this, 0, 0);
        }
        if (objectOption2) {
            Engine.packets.objectOption2.handlePacket(this, 0, 0);
        }
        if (attackingPlayer) {
            Engine.playerCombat.attackPlayer(this);
        }
        if (jumpUpdateReq) {
	     if(jumpDelay >= 1) {
			runEmote = walkEmote = 2750;
			updateReq = appearanceUpdateReq = true;
	     }
	     if(jumpDelay <= 0) {
			playerWeapon.setWeapon();
			jumpDelay = 0;
			updateReq = appearanceUpdateReq = true;
	     }
	     jumpUpdateReq = false;
        }
        if (skulledUpdateReq) {
	     if(skulledDelay >= 1) {
			pkIcon = 0;
			updateReq = appearanceUpdateReq = true;
	     }
	     if(skulledDelay <= 0) {
			pkIcon = -1;
			skulledDelay = 0;
			updateReq = appearanceUpdateReq = true;
	     }
	     skulledUpdateReq = false;
        }
        if (runEnergyUpdateReq) {
            frames.setEnergy(this);
            runEnergyUpdateReq = false;
        }
        if (specialAmountUpdateReq) {
		frames.setConfig(this, 300, specialAmount*10);
            specialAmountUpdateReq = false;
        }
        if (afterDeathUpdateReq) {
	     for(int i = 0; i < skillLvl.length; i++) {
			skillLvl[i] = getLevelForXP(i);
	      	frames.setSkillLvl(this, i);
	     }
			skulledDelay = 0; 
			specialAmount = 100;
			runEnergy = 100;
			deathDelay = 7;
			specialAmountUpdateReq = true;
			runEnergyUpdateReq = true;
			skulledUpdateReq = true;
			isDead = false;
			afterDeathUpdateReq = false;
        }
        if (statRestoreDelay <= 0) {
            for (int i1 = 0; i1 < skillLvl.length; i1++) {
                int xpLvl = getLevelForXP(i1);
                if (skillLvl[i1] < xpLvl) {
                    skillLvl[i1]++;
                    frames.setSkillLvl(this, i1);
                } else if (skillLvl[i1] > xpLvl) {
                    skillLvl[i1]--;
                    frames.setSkillLvl(this, i1);
                }
            }
            statRestoreDelay = 75;
        }
        if (teleDelay == 0) {
            teleDelay = -1;
            setCoords(teleX, teleY, heightLevel);
            requestAnim(teleFinishAnim, 0);
            requestGFX(teleFinishGFX, teleFinishGFXHeight);
            teleX = teleY = -1;
        }
        if (clickDelay == 0) {
            clickDelay = -1;
        }
	  checkForAttackOption();
    }

	public void dropAllItems(Player p) {
        Player p2 = Engine.players[p.attackPlayer];
		if (p2 == null) {
			return;
		}
		for (int i = 0; i < items.length; i++) {
			if (items[i] > 0) {
                if (Engine.items.isUntradable(items[i])) {
                    Engine.items.createGroundItem(items[i], itemsN[i], absX, absY, heightLevel, username);
                } else {
					Engine.items.createGroundItem(items[i], itemsN[i], absX, absY, heightLevel, p2.username);
				}
				items[i] = -1;
				itemsN[i] = 0;
			}
		}
		for (int i = 0; i < equipment.length; i++) {
			if (equipment[i] > 0) {
                if (Engine.items.isUntradable(equipment[i])) {
                    Engine.items.createGroundItem(equipment[i], equipmentN[i], absX, absY, heightLevel, username);
                } else {
					Engine.items.createGroundItem(equipment[i], equipmentN[i], absX, absY, heightLevel, p2.username);
				}
				equipment[i] = -1;
				equipmentN[i] = 0;
			}
		}
			Engine.items.createGroundItem(526, 1, absX, absY, heightLevel, p2.username); // drop bones
			deathMessage = Misc.random(8);
			if(deathMessage == 0) {
				p.frames.sendMessage(p2, "With a crushing blow, you defeat "+username+".");
			} else if(deathMessage == 1) {
				p.frames.sendMessage(p2, "It's a humiliating defeat for "+username+".");
			} else if(deathMessage == 2) { 
				p.frames.sendMessage(p2, username+" didn't stand a chance against you.");
			} else if(deathMessage == 3) {
				p.frames.sendMessage(p2, "You have defeated "+username+".");
			} else if(deathMessage == 4) {
				p.frames.sendMessage(p2, username+" regrets the day they met you in combat.");
			} else if(deathMessage == 5) {
				p.frames.sendMessage(p2, "It's all over for "+username+".");
			} else if(deathMessage == 6) {
				p.frames.sendMessage(p2, username+" falls before your might.");
			} else if(deathMessage == 7) {
				p.frames.sendMessage(p2, "Can anyone defeat you? Certainly not "+username+".");
			} else if(deathMessage == 8) {
				p.frames.sendMessage(p2, "You were clearly a better fighter than "+username+".");
		}
		frames.setItems(this, 149, 0, 93, items, itemsN);
		frames.setItems(this, 387, 28, 94, equipment, equipmentN);
		playerWeapon.setWeapon();
		calculateEquipmentBonus();
	}

    /**
     * Get xp based on your level.
     * @param skillId The skill level to get the level based off XP for.
     * @return Returns the level based on the amount of XP the specified skill has.
     */
    public int getLevelForXP(int skillId) {
        int exp = skillXP[skillId];
        int points = 0;
        int output = 0;
        for (int lvl = 1; lvl < 100; lvl++) {
            points += Math.floor((double)lvl + 300.0 * Math.pow(2.0, (double)lvl / 7.0));
            output = (int)Math.floor(points / 4);
            if ((output - 1) >= exp) {
                return lvl;
            }
        }
        return 99;
    }

    /**
     * Death data.
     */
      public void applyDead() {
	     if(deathDelay >= 7) {
		      if(faceToReq != 65535) {
				requestFaceTo(65535);
	            }
	     }
			requestAnim(7197, 0);
			requestGFX(-1, 0);
	     if(deathDelay <= 0) {
			dropAllItems(this);
			frames.sendMessage(this, "Oh dear you are dead.");
			setCoords(3242, 3520, 0);
			afterDeathUpdateReq = true;
	     }
	}

    /**
     * Calculates equipment bonus.
     */
    public void calculateEquipmentBonus() {
        for (int i = 0; i < equipmentBonus.length; i++) {
            equipmentBonus[i] = 0;
        }
        for (int i = 0; i < equipment.length; i++) {
            if (equipment[i] > -1) {
                for (int j = 0; j < Engine.items.maxListedItems; j++) {
                    if (Engine.items.itemLists[j] != null) {
                        if (Engine.items.itemLists[j].itemId == equipment[i]) {
                            for (int k = 0; k < equipmentBonus.length; k++) {
                                equipmentBonus[k] += Engine.items.itemLists[j].bonuses[k];
                            }
                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * Writes the equipment bonus.
     */
    public void setEquipmentBonus() {
        String[] bonusNames = Misc.bonusNames;
        int id = 35;
        for (int i = 0; i < equipmentBonus.length; i++) {
            frames.setString(this, bonusNames[i] + ": " + (equipmentBonus[i] >= 0 ? "+" : "") + equipmentBonus[i], 667, id++);
            if (id == 45) {
                id = 47;
            }
        }
        frames.setString(this, "Summoning: +0", 667, 45);
    }

    public void openBank() {
        frames.setConfig2(this, 563, 4194304);
        frames.setConfig2(this, 1248, -2013265920);
        frames.showInterface(this, 762);
        frames.setInventory(this, 763);
        frames.setBankOptions(this);
        frames.setItems(this, -1, 64207, 95, bankItems, bankItemsN);
        frames.setItems(this, -1, 64209, 93, items, itemsN);
	  frames.setString(this, bankItemCount()+"", 762, 97);
    }

    public void updateHP(int chHp, boolean heal) {
        if (heal) {
            skillLvl[3] += chHp;
            if (skillLvl[3] > getLevelForXP(3)) {
                skillLvl[3] = getLevelForXP(3);
            }
        } else if (!heal) {
            skillLvl[3] -= chHp;
            if (skillLvl[3] <= 0) {
                skillLvl[3] = 0;
                isDead = true;
                Engine.playerMovement.resetWalkingQueue(this);
            }
        }
        frames.setSkillLvl(this, 3);
    }

    /**
     * Add experiance to a specific skill.
     * @param amount The amoubt of XP you want to add.
     * @param skill The skill id you want to add it to.
     */
	public void addSkillXP(double amount, int skill) {
        if(skill > skillXP.length || skill < 0) {
            return;
        }
        int oldLevel = getLevelForXP(skill);
        skillXP[skill] += amount;
        int newLevel = getLevelForXP(skill);
        if(oldLevel < newLevel) {
            if(skill == 3) {
                updateHP(newLevel - oldLevel, true);
            } else {
                skillLvl[skill] += (newLevel - oldLevel);
            }
			frames.setSkillLvl(this, skill);
            appearanceUpdateReq = true;
            updateReq = true;
        }
        frames.setSkillLvl(this, skill);
    }

    /**
     * Teleports a player.
     * @param x The x coordinate to teleport to.
     * @param y The y coordinate to teleport to.
     * @param height The height level to teleport to.
     * @param delay The delay before the teleport is done.
     * @param distance The offset you can teleport to, such as 1 for a max offset of x +/- 1 and y +/- 1.
     * @param emoteStart The emote to do right away.
     * @param emoteEnd The emote to do after teleporting.
     * @param gfxStart The graphic to do right away.
     * @param gfxStartH The height level to create the start graphic at.
     * @param gfxEnd The graphic to do after the teleport is done.
     * @param gfxEndH The finish graphic height.
     */
    public void teleportTo(int x, int y, int height, int delay, int distance, int emoteStart, int emoteEnd, int gfxStart, 
            int gfxStartH, int gfxEnd, int gfxEndH) {
        itemPickup = false;
        playerOption1 = false;
        playerOption2 = false;
        playerOption3 = false;
        npcOption1 = false;
        npcOption2 = false;
        objectOption1 = false;
        objectOption2 = false;
        attackingPlayer = false;
        clickDelay = delay + 2;
        teleDelay = delay;
        if (distance > 0) {
            int xType = Misc.random(1);
            int yType = Misc.random(1);
            int xOffset = Misc.random(distance);
            int yOffset = Misc.random(distance);
            if (xType == 1)
                x += -xOffset;
            else
                x += xOffset;
            if(yType == 1)
                y += -yOffset;
            else
                y += yOffset;
        }
        teleX = x;
        teleY = y;
        heightLevel = height;
        Engine.playerMovement.resetWalkingQueue(this);
        requestAnim(emoteStart, 0);
        requestGFX(gfxStart, gfxStartH);
        teleFinishGFX = gfxEnd;
        teleFinishGFXHeight = gfxEndH;
        teleFinishAnim = emoteEnd;
    }

    /**
     * Set the player's coordinates.
     * @param x The x coordinate to teleport to.
     * @param y The y coordinate to teleport to.
     */
    public void setCoords(int x, int y, int height) {
        teleportToX = x;
        teleportToY = y;
        heightLevel = height;
        didTeleport = true;
    }

    public void checkForAttackOption()
    {
        if(showAttackOption != Engine.wildernessArea(absX, absY))
        {
            showAttackOption = Engine.wildernessArea(absX, absY);
            if(showAttackOption)
            {
                frames.setPlayerOption(this, "Attack", 1);
            }
            else
            {
                frames.setPlayerOption(this, "null", 1);
            }
        }
    }

    /**
     * Req an animation for this player.
     * @param animId The amination to perform.
     * @param animD The delay before doing the animation.
     */
    public void requestAnim(int animId, int animD) {
        animReq = animId;
        animDelay = animD;
        animUpdateReq = true;
        updateReq = true;
    }

    /**
     * Req an graphic for this player.
     * @param gfxId The graphic to perform.
     * @param gfxD The delay or height or the gfx depending on the value.
     */
    public void requestGFX(int gfxId, int gfxD) {
        if (gfxD >= 100) {
            gfxD += 6553500;
        }
        gfxReq = gfxId;
        gfxDelay = gfxD;
        gfxUpdateReq = true;
        updateReq = true;
    }

    /**
     * Req this player faces NPC or player.
     * @param faceId The target to face.
     */
    public void requestFaceTo(int faceId) {
        faceToReq = faceId;
        faceToUpdateReq = true;
        updateReq = true;
    }

    /**
     * Append damage.
     */
    public void appendHit(int damage, int posion) {
        if (damage > skillLvl[3]) {
            damage = skillLvl[3];
        }
        updateHP(damage, false);
        if (!hit1UpdateReq) {
            hitDiff1 = damage;
            posionHit1 = posion;
            hit1UpdateReq = true;
        } else {
            hitDiff2 = damage;
            posionHit2 = posion;
            hit2UpdateReq = true;
        }
        updateReq = true;
    }

    /**
     * Force chat text.
     */
    public void requestForceChat(String s) {
        forceChat = s;
        forceChatUpdateReq = true;
        updateReq = true;
    }

    /**
     * Prepare player for removal.
     */
    public void destruct() {
        stream = null;
        try {
            socket.input.close();
            socket.output.close();
            socket.socket.close();
        } catch (Exception e) {
        }
        socket.input = null;
        socket.output = null;
        socket.socket = null;
        socket = null;
        absX = absY = mapRegionX = mapRegionY = -1;
    }

    public int bankItemCount() {
    	  int count = 0;
        for(int i = 0; i < bankItems.length; i++) {
        if(bankItems[i] > 0 && bankItemsN[i] > 0)
            count++;
        else
            break;
    }
    	  return count;

    }
    public void reqWalkQueue(int x, int y) {
	  int firstX = x - (mapRegionX - 6) * 8;
	  int firstY = y - (mapRegionY - 6) * 8;
	  Engine.playerMovement.resetWalkingQueue(this);
	  Engine.playerMovement.addToWalkingQueue(this, firstX, firstY);
    }
    public boolean canAttackPlayer(Player p) {
     	  Player p2 = Engine.players[p.attackPlayer];
	  if(p == null || p.isDead) {
		return false;
	  }
	  else if(p.attackPlayer < 1 || p.attackPlayer >= Engine.players.length || Engine.players[p.attackPlayer] == null) {
		return false;
	  }
	  if(!Engine.wildernessArea(p.absX, p.absY)) {
	  	return false;
	  }
	  if(!Engine.wildernessArea(p2.absX, p2.absY)) {
		return false;
	  }
		return true;
	  }
}